package com.mt.api.modules.service.impl;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.mt.common.response.WebResponse;
import com.mt.common.response.WebResponseUtils;
import com.mt.api.constants.enums.StockTakingStatusEnum;
import com.mt.api.modules.domain.*;
import com.mt.api.modules.domain.bo.AppOrderDetailSkuAddBo;
import com.mt.api.modules.domain.bo.StockTakingAddBo;
import com.mt.api.modules.domain.bo.StockTakingCancelBo;
import com.mt.api.modules.domain.bo.StockTakingPageBo;
import com.mt.api.modules.domain.vo.StockTakingAndDetailVo;
import com.mt.api.modules.domain.vo.StockTakingDetailVo;
import com.mt.api.modules.domain.vo.StockTakingVo;
import com.mt.api.modules.manager.*;
import com.mt.api.modules.mapstruct.StockTakingDetailMapStruct;
import com.mt.api.modules.mapstruct.StockTakingMapStruct;
import com.mt.api.modules.service.IStockTakingService;
import com.mt.api.util.AmountUtil;
import com.mt.api.util.SequenceBuilder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * @Author: plover
 * @Date: 2022-04-30
 * @Description:
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StockTakingServiceImpl implements IStockTakingService {

    private final IStockTakingManager stockTakingManager;
    private final IStockTakingDetailManager stockTakingDetailManager;
    private final IStockManager stockManager;
    private final ISkuManager skuManager;
    private final ICargoManager cargoManager;

    private final StockTakingMapStruct stockTakingMapStruct;
    private final StockTakingDetailMapStruct stockTakingDetailMapStruct;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public WebResponse addStockTaking(StockTakingAddBo bo) {
        List<StockTakingAddBo.StockTakingAddDetail> stockTakingDetailList = bo.getStockTakingDetailList();
        if (CollectionUtils.isEmpty(stockTakingDetailList)) {
            return WebResponseUtils.errorParam("盘点明细不能为空");
        }

        SequenceBuilder builder = new SequenceBuilder();
        StockTaking stockTaking = new StockTaking();
        stockTaking.setStockTakingNo(builder.builderStockTakingNo());
        stockTaking.setStatus(StockTakingStatusEnum.CANCEL.getCode());
        stockTaking.setRemark(bo.getRemark());
        stockTakingManager.save(stockTaking);
        for (StockTakingAddBo.StockTakingAddDetail stockTakingAddDetail : stockTakingDetailList) {
            List<AppOrderDetailSkuAddBo> skuInfoList = stockTakingAddDetail.getSkuInfoList();
            for (AppOrderDetailSkuAddBo skuInfo : skuInfoList) {

                Integer skuId = skuInfo.getSkuId();
                Integer qty = skuInfo.getQty();
                if (Objects.isNull(qty) || qty == 0 || Objects.isNull(skuId)) {
                    continue;
                }
                AppSku sku = skuManager.getSkuById(skuId);
                if (Objects.isNull(sku)) {
                    log.info("addStockTaking skuId not exists, bo: {}, skuId: {}", bo, skuId);
                    continue;
                }

                StockTakingDetail stockTakingDetail = new StockTakingDetail();

                //更新库存
                AppStock stock = stockManager.getStockBySkuId(skuId);
                if (Objects.nonNull(stock)) {
                    stockTakingDetail.setBeforeQty(stock.getQty());
                    stockManager.updateQtyById(stock.getId(), qty);
                } else {
                    stockTakingDetail.setBeforeQty(0);
                    stock = AppStock.builder().skuCode(sku.getSkuCode()).skuId(skuId)
                            .cargoNo(sku.getCargoNo()).cargoId(sku.getCargoId()).color(sku.getColor()).size(sku.getSize()).qty(qty).totalQty(qty)
                            .build();
                    stockManager.save(stock);
                }
                stockTakingDetail.setStockTakingId(stockTaking.getId());
                stockTakingDetail.setSkuId(sku.getId());
                stockTakingDetail.setSkuCode(sku.getSkuCode());
                stockTakingDetail.setCargoNo(sku.getCargoNo());
                stockTakingDetail.setCargoId(sku.getCargoId());
                stockTakingDetail.setColor(sku.getColor());
                stockTakingDetail.setSize(sku.getSize());
                stockTakingDetail.setQty(qty);
                stockTakingDetail.setChangeQty(qty - stock.getQty());
                stockTakingDetailManager.save(stockTakingDetail);
            }
        }
        return WebResponseUtils.success();
    }

    @Override
    public WebResponse getStockTakingPage(StockTakingPageBo bo) {
        Page page = stockTakingManager.getStockTakingPage(bo);
        List<StockTaking> records = page.getRecords();
        List<StockTakingVo> stockTakingVoList = stockTakingMapStruct.toVoList(records);
        for (StockTakingVo stockTakingVo : stockTakingVoList) {
            List<StockTakingDetail> stockTakingDetailList = stockTakingDetailManager.getListByStockTakingId(stockTakingVo.getId());
            int sum = stockTakingDetailList.stream().mapToInt(StockTakingDetail::getChangeQty).sum();

            int amount = 0;
            for (StockTakingDetail stockTakingDetail : stockTakingDetailList) {
                AppCargo cargo = cargoManager.getById(stockTakingDetail.getCargoId());
                amount += cargo.getPurchasePrice() * stockTakingDetail.getChangeQty();
            }
            stockTakingVo.setAmount(AmountUtil.divideHundred(amount));
            stockTakingVo.setQty(sum);
        }
        page.setRecords(stockTakingVoList);
        return WebResponseUtils.successPage(page);
    }

    @Override
    public WebResponse<StockTakingAndDetailVo> getStockTakingDetail(Integer id) {
        StockTaking stockTaking = stockTakingManager.getById(id);
        if (Objects.isNull(stockTaking)) {
            return WebResponseUtils.errorParam("盘点单不存在");
        }
        StockTakingAndDetailVo vo = new StockTakingAndDetailVo();
        StockTakingVo stockTakingVo = stockTakingMapStruct.toVo(stockTaking);
        int totalAmount = 0;
        int qty = 0;
        List<StockTakingDetail> stockTakingDetailList = stockTakingDetailManager.getListByStockTakingId(id);
        List<StockTakingDetailVo> stockTakingDetailVoList = Lists.newArrayList();
        for (StockTakingDetail stockTakingDetail : stockTakingDetailList) {
            StockTakingDetailVo stockTakingDetailVo = stockTakingDetailMapStruct.toVo(stockTakingDetail);
            AppCargo cargo = cargoManager.getById(stockTakingDetailVo.getCargoId());
            Integer changeAmount = cargo.getPurchasePrice() * stockTakingDetailVo.getChangeQty();
            totalAmount = totalAmount + changeAmount;
            qty = qty + stockTakingDetailVo.getChangeQty();
            stockTakingDetailVo.setChangeAmount(AmountUtil.divideHundred(changeAmount));
            stockTakingDetailVoList.add(stockTakingDetailVo);
        }
        stockTakingVo.setQty(qty);
        stockTakingVo.setAmount(AmountUtil.divideHundred(totalAmount));
        vo.setStockTaking(stockTakingVo);
        vo.setStockTakingDetailList(stockTakingDetailVoList);
        return WebResponseUtils.success(vo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public WebResponse cancelStockTaking(StockTakingCancelBo bo) {
        StockTaking stockTaking = stockTakingManager.getById(bo.getStockTakingId());
        if (Objects.isNull(stockTaking)) {
            return WebResponseUtils.errorParam("盘点单不存在");
        }
        StockTaking upStockTaking = new StockTaking();
        upStockTaking.setId(bo.getStockTakingId());
        upStockTaking.setStatus(StockTakingStatusEnum.CANCEL.getCode());
        stockTakingManager.updateById(upStockTaking);

        List<StockTakingDetail> stockTakingDetailList = stockTakingDetailManager.getListByStockTakingId(bo.getStockTakingId());
        for (StockTakingDetail stockTakingDetail : stockTakingDetailList) {
            Integer skuId = stockTakingDetail.getSkuId();
            stockManager.subtractQtyBySkuId(skuId, stockTakingDetail.getChangeQty());
        }
        return WebResponseUtils.success();
    }
}
